import javax.print.PrintService;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.print.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * 票据打印主应用
 */
public class BillPrinterApp extends JFrame {
    private BillTemplate template = new BillTemplate();
    private Map<String, JTextField> dataFields = new HashMap<>();
    private JPanel dataPanel;
    private JLabel templateLabel;
    
    public BillPrinterApp() {
        setTitle("Java票据套打应用");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initComponents();
        setLocationRelativeTo(null);
    }
    
    private void initComponents() {
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
        
        // 模板管理区域
        JPanel templatePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        templatePanel.add(new JLabel("当前模板:"));
        templateLabel = new JLabel(template.getTemplateName());
        templatePanel.add(templateLabel);
        
        JButton newTemplateButton = new JButton("新建模板");
        JButton loadTemplateButton = new JButton("加载模板");
        JButton saveTemplateButton = new JButton("保存模板");
        
        newTemplateButton.addActionListener(this::newTemplateAction);
        loadTemplateButton.addActionListener(this::loadTemplateAction);
        saveTemplateButton.addActionListener(this::saveTemplateAction);
        
        templatePanel.add(newTemplateButton);
        templatePanel.add(loadTemplateButton);
        templatePanel.add(saveTemplateButton);
        
        mainPanel.add(templatePanel, BorderLayout.NORTH);
        
        // 数据输入区域
        dataPanel = new JPanel();
        dataPanel.setLayout(new BoxLayout(dataPanel, BoxLayout.Y_AXIS));
        
        JScrollPane scrollPane = new JScrollPane(dataPanel);
        mainPanel.add(scrollPane, BorderLayout.CENTER);
        
        // 打印按钮区域
        JPanel buttonPanel = new JPanel();
        JButton previewButton = new JButton("打印预览");
        JButton printButton = new JButton("直接打印");
        
        previewButton.addActionListener(this::previewPrintAction);
        printButton.addActionListener(this::directPrintAction);
        
        buttonPanel.add(previewButton);
        buttonPanel.add(printButton);
        
        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
        
        setContentPane(mainPanel);
        updateDataInputs();
    }
    
    private void updateDataInputs() {
        dataPanel.removeAll();
        dataFields.clear();
        
        for (BillTemplate.FieldInfo field : template.getFields()) {
            JPanel fieldPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
            fieldPanel.add(new JLabel(field.getName() + ":"));
            
            JTextField textField = new JTextField(20);
            fieldPanel.add(textField);
            dataFields.put(field.getName(), textField);
            
            dataPanel.add(fieldPanel);
        }
        
        dataPanel.revalidate();
        dataPanel.repaint();
    }
    
    private void newTemplateAction(ActionEvent e) {
        TemplateEditorDialog dialog = new TemplateEditorDialog(this, null);
        dialog.setVisible(true);
        
        if (dialog.getTemplate() != null) {
            template = dialog.getTemplate();
            templateLabel.setText(template.getTemplateName());
            updateDataInputs();
        }
    }
    
    private void loadTemplateAction(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".json");
            }
            
            @Override
            public String getDescription() {
                return "JSON 文件 (*.json)";
            }
        });
        
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            try {
                template = BillTemplate.loadFromFile(fileChooser.getSelectedFile().getAbsolutePath());
                templateLabel.setText(template.getTemplateName());
                updateDataInputs();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "加载模板失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    private void saveTemplateAction(ActionEvent e) {
        if (template.getFields().isEmpty()) {
            JOptionPane.showMessageDialog(this, "模板为空，无法保存", "警告", JOptionPane.WARNING_MESSAGE);
            return;
        }
        
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setSelectedFile(new File(template.getTemplateName() + ".json"));
        fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toLowerCase().endsWith(".json");
            }
            
            @Override
            public String getDescription() {
                return "JSON 文件 (*.json)";
            }
        });
        
        int result = fileChooser.showSaveDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            try {
                String fileName = fileChooser.getSelectedFile().getAbsolutePath();
                if (!fileName.toLowerCase().endsWith(".json")) {
                    fileName += ".json";
                }
                template.saveToFile(fileName);
                JOptionPane.showMessageDialog(this, "模板保存成功", "成功", JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "保存模板失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    private void previewPrintAction(ActionEvent e) {
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(new BillPrintable());
        
        if (job.printDialog()) {
            try {
                job.print();
            } catch (PrinterException ex) {
                JOptionPane.showMessageDialog(this, "打印失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    
    private void directPrintAction(ActionEvent e) {
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(new BillPrintable());
        
        try {
            job.print();
        } catch (PrinterException ex) {
            JOptionPane.showMessageDialog(this, "打印失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /**
     * 打印内容类
     */
    private class BillPrintable implements Printable {
        @Override
        public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
            if (page > 0) {
                return NO_SUCH_PAGE;
            }
            
            Graphics2D g2d = (Graphics2D) g;
            
            // 设置字体和抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            // 获取打印机的DPI信息
            double dpiX = 72.0; // 默认DPI值
            double dpiY = 72.0;
            
            // 尝试从打印环境获取DPI
            try {
                PrintService service = PrinterJob.getPrinterJob().getPrintService();
                if (service != null) {
                    // 尝试使用PrinterResolution属性获取DPI
                    AttributeSet attributes = service.getAttributes();
                    PrinterResolution resolution = (PrinterResolution) attributes.get(PrinterResolution.class);
                    
                    if (resolution != null) {
                        dpiX = resolution.getResolution(PrinterResolution.DPI)[0];
                        dpiY = resolution.getResolution(PrinterResolution.DPI)[1];
                        System.out.println("使用打印机DPI: " + dpiX + "x" + dpiY);
                    } else {
                        // 尝试使用MediaPrintableArea属性计算DPI
                        MediaPrintableArea area = (MediaPrintableArea) attributes.get(MediaPrintableArea.class);
                        if (area != null) {
                            // 获取纸张尺寸
                            MediaSizeName mediaSize = (MediaSizeName) attributes.get(MediaSizeName.class);
                            if (mediaSize != null) {
                                MediaSize size = MediaSize.getMediaSizeForName(mediaSize);
                                float paperWidth = size.getX(MediaPrintableArea.INCH);
                                float paperHeight = size.getY(MediaPrintableArea.INCH);
                                
                                // 计算DPI (使用打印区域与纸张尺寸的比例)
                                float printableWidth = area.getWidth(MediaPrintableArea.INCH);
                                float printableHeight = area.getHeight(MediaPrintableArea.INCH);
                                
                                // 使用打印区域与纸张尺寸的比例估计DPI
                                if (paperWidth > 0 && paperHeight > 0) {
                                    dpiX = pf.getWidth() / paperWidth;
                                    dpiY = pf.getHeight() / paperHeight;
                                    System.out.println("估计打印机DPI: " + dpiX + "x" + dpiY);
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                // 记录错误但继续使用默认值
                System.err.println("获取打印机DPI信息失败: " + e.getMessage());
            }
            
            // 如果仍然无法获取DPI，尝试使用Toolkit的屏幕分辨率
            if (dpiX <= 0 || dpiY <= 0) {
                try {
                    dpiX = Toolkit.getDefaultToolkit().getScreenResolution();
                    dpiY = Toolkit.getDefaultToolkit().getScreenResolution();
                    System.out.println("使用屏幕DPI: " + dpiX + "x" + dpiY);
                } catch (Exception e) {
                    // 最后手段：使用标准72 DPI
                    dpiX = 72.0;
                    dpiY = 72.0;
                    System.out.println("使用默认DPI: " + dpiX + "x" + dpiY);
                }
            }
            
            // 打印每个字段
            for (BillTemplate.FieldInfo field : template.getFields()) {
                String fieldName = field.getName();
                String fieldValue = dataFields.getOrDefault(fieldName, new JTextField()).getText();
                
                // 使用实际DPI进行毫米到点的转换
                float x = field.getX() * (float) dpiX / 25.4f;
                float y = field.getY() * (float) dpiY / 25.4f;
                float width = field.getWidth() * (float) dpiX / 25.4f;
                float height = field.getHeight() * (float) dpiY / 25.4f;
                
                // 设置字体大小
                Font font = new Font("宋体", Font.PLAIN, Math.round(field.getFontSize()));
                g2d.setFont(font);
                
                // 绘制文本
                g2d.drawString(fieldValue, x, y + height);
            }
            
            return PAGE_EXISTS;
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                // 设置系统外观
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            new BillPrinterApp().setVisible(true);
        });
    }
}
